/*
 * Position.java
 *
 * contains the full board with the position of each piece,
 * the turn, and other useful informations to know the exact
 * status of the game.
 */

package strugglechess;

import java.util.ArrayList;

/**
 * @author Olivier Herau
 *
 */
public class Position {

    // TODO put those constant values in a separate class
    // Empty square
    int EMPTY = 0;
    // White pieces
    int WP = 1;
    int WN = 2;
    int WB = 3;
    int WR = 4;
    int WQ = 5;
    int WK = 6;
    // Black pieces
    int BP = 7;
    int BN = 8;
    int BB = 9;
    int BR = 10;
    int BQ = 11;
    int BK = 12;


    private int turn;
    private int[] board = null;
    private int WHITE_TO_MOVE = 0;
    private int BLACK_TO_MOVE = 1;

    private int COLOR_WHITE = 0;
    private int COLOR_BLACK = 1;

    public void setWhiteToMove() {
        turn = WHITE_TO_MOVE;
    }

    public void setBlackToMove() {
        turn = BLACK_TO_MOVE;
    }

    public boolean isWhiteToMove() {
        return (turn == WHITE_TO_MOVE);
    }

    public boolean isBlackToMove() {
        return (turn == BLACK_TO_MOVE);
    }

    /**
     * class Constructor
     */
    public Position() {
        board = new int[64];
        for(int i=0;i<64;i++) {
            board[i]=0;
        }
    }

    /*
     * Create a new position by copy
     */
    public Position(Position position) {
        board = new int[64];
        for(int i=0;i<64;i++) {
            board[i]=position.board[i];
        }
        turn = position.turn;
    }

    /**
     * Set the position for a new game
     * @return the position
     */
    public Position newGame() {

        // Set the Pawns
        for(int i=1;i<9;i++)
        {
           setPiece(WP,i,2);
           setPiece(BP,i,7);
        }

        // Set the Rooks
        setPiece(WR,1,1);
        setPiece(WR,8,1);
        setPiece(BR,1,8);
        setPiece(BR,8,8);

        // Set the Knights
        setPiece(WN,2,1);
        setPiece(WN,7,1);
        setPiece(BN,2,8);
        setPiece(BN,7,8);

        // Set the Bishops
        setPiece(WB,3,1);
        setPiece(WB,6,1);
        setPiece(BB,3,8);
        setPiece(BB,6,8);

        // Set the Queens
        setPiece(WQ,4,1);
        setPiece(BQ,4,8);

        // Set the Kings
        setPiece(WK,5,1);
        setPiece(BK,5,8);

        // Set white make the first move
        setWhiteToMove();

        return this;
    }

    /**
     * Set a piece to the given position
     * @param pieceCode the code of the piece to set up
     * @param col the column
     * @param row the row
     */
    public void setPiece(int pieceCode, int col, int row) {
        board[col-1 + 8*(row-1)] = pieceCode;
    }


    public void movePiece(int col1, int row1, int col2, int row2) {
        int pieceCode = getPiece(col1, row1);
        setPiece(EMPTY, col1, row1);
        setPiece(pieceCode, col2, row2);
    }

    public int getPiece(int col, int row) {

        int pieceCode = board[col-1 + 8*(row-1)];
        return pieceCode;
    }

    /*
     * Get the pieces left on the board (useful for evaluation of positions)
     */
    public int[] getPiecesLeft() {

        int[] pieces = new int[12];
        for(int c=0; c<12;c++) {
            pieces[c] = 0;
        }

        int p;
        for(int i=0;i<64;i++) {
            p=board[i];
            if(p!=0) {
                (pieces[p-1])++ ;
            }
        }

        return pieces;
    }

    /*
     * Apply the move to the position
     */
    public Position move(int c1, int r1, int c2, int r2) {
        int piece = getPiece(c1, r1);
        setPiece(piece, c2, r2);
        setPiece(EMPTY, c1, r1);
        changeTurn();
        return this;
    }

    /*
     * Change the turn
     */
    private int changeTurn() {
        //turn = 1 - turn;
        turn = (turn==WHITE_TO_MOVE)?(BLACK_TO_MOVE):(WHITE_TO_MOVE);
        return turn;
    }

    public boolean isSquareEmpty(int col, int row) {
        return (getPiece(col, row) == EMPTY);
    }

    public int getTurn() {
        return turn;
    }

        /*
     * Indicates if the piece is playable for the given player
     */
    public boolean isPiecePlayable(int col, int row) {
        int pieceCode = getPiece(col, row);
        if(turn == WHITE_TO_MOVE) {
            return isPieceWhite(pieceCode);
        }
        else {
            return isPieceBlack(pieceCode);
        }
    }

    public boolean isPieceWhite(int pieceCode) {
        return (pieceCode == WP
                    || pieceCode == WR
                    || pieceCode == WN
                    || pieceCode == WB
                    || pieceCode == WQ
                    || pieceCode == WK);
    }

    public boolean isPieceBlack(int pieceCode) {
        return (pieceCode == BP
                    || pieceCode == BR
                    || pieceCode == BN
                    || pieceCode == BB
                    || pieceCode == BQ
                    || pieceCode == BK);
    }




    /*
     *
     */
    public ArrayList<Move> getPossibleMoves() {

        // TODO : implement this method (move the code from class Engine to this one)
        return null;
    }

    /*
     * Return if the square is empty or occupied by a piece of the opponent
     */
    public boolean isEmptyOrOpponent(int col,int row) {
        int pieceCode = getPiece(col, row);
        if (pieceCode == EMPTY) return true;
        if(isWhiteToMove()) return isPieceBlack(pieceCode);
        if(isBlackToMove()) return isPieceWhite(pieceCode);
        return false;
    }

    void move(Move m) {
        move(m.col1,m.row1,m.col2,m.row2);
    }
}
